package geometry;

/**
 * Represents a mathematical vector in 2D space.  Vectors are defined by a direction and a magnitude.  Should the length be negative, the Vector is considered to be facing the opposite direction in the same magnitude.
 *
 * @author Catastrophe
 */
public final class Vector2D
{
	/**
	 * The Point2D at the head of this vector assuming the tail is at the origin.
	 */
	private Point2D head;

	/**
	 * @return a unit vector in the direction of the positive X axis.
	 */
	public static Vector2D xAxis()
	{
		return new Vector2D(new Point2D(1.0, 0.0));
	}

	/**
	 * @return a unit vector in the direction of the positive Y axis.
	 */
	public static Vector2D yAxis()
	{
		return new Vector2D(new Point2D(0.0, 1.0));
	}

	/**
	 * Creates a new Vector2D.
	 *
	 * @param head the Point2D marking the head of the Vector assuming the tail is at the origin.
	 * @throws NullPointerException if the specified Point2D is <code>null</code>.
	 */
	public Vector2D(Point2D head) throws NullPointerException
	{
		if(head == null)
			throw new NullPointerException();
		this.head = head;
	}

	/**
	 * Creates a new Vector2D.
	 *
	 * @param head the Point2D marking the head of the Vector.
	 * @param tail the Point2D marking the tail of the Vector.
	 * @throws NullPointerException if either of the specified Point2D is <code>null</code>.
	 */
	public Vector2D(Point2D head, Point2D tail) throws NullPointerException
	{
		if(head == null || tail == null)
			throw new NullPointerException();
		this.head = new Point2D(head.getX() - tail.getX(), head.getY() - tail.getY());
	}

	/**
	 * Creates a new Vector2D.
	 *
	 * @param angle the Angle between the positive X axis and the Vector2D.
	 * @param magnitude the magnitude of the new Vector2D.
	 * @throws NullPointerException if the specified Angle is <code>null</code>.
	 */
	public Vector2D(Angle angle, double magnitude) throws NullPointerException
	{
		this.head = new Point2D(angle.cos() * magnitude, angle.sin() * magnitude);
	}

	/**
	 * @return the head of this Vector2D assuming its tail is at the origin.
	 */
	public Point2D head()
	{
		return head;
	}

	/**
	 * @return the magnitude of this Vector.
	 */
	public double magnitude()
	{
		return head.distanceTo(Point2D.origin());
	}

	/**
	 * Changes the direction of this Vector to point in the opposite direction.  The length remains unchanged.
	 */
	public void invert()
	{
		head.invert();
	}

	/**
	 * Multiplies this Vector by a scalar value.
	 *
	 * @param multiplier the scalar multiplier.
	 */
	public void scalarMultiply(double multiplier)
	{
		head = Utility.multiple(head, multiplier);
	}
}